#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<set>
#include"Log.hpp"
#include"InetAddr.hpp"

class Command
{
public:
    Command()
    {
        _safe_command.insert("ls");
        _safe_command.insert("touch");
        _safe_command.insert("pwd");
        _safe_command.insert("whoami");
        _safe_command.insert("which");
    }
    ~Command()
    {} 
    //安全检查
    bool SafeCheck(const std::string &cmdstr)
    {
        for(auto& cmd : _safe_command)
        {
            if(strncmp(cmd.c_str(), cmdstr.c_str(), cmd.size()) == 0)
            {
                return true;
            }
        }
        return false;
    }
    std::string Execute(const std::string &cmdstr)
    {
        if(!SafeCheck(cmdstr))
        {
            return "command is not safe";
        }
        FILE *fp = popen(cmdstr.c_str(), "r"); // popen自动创建一个进程 返回结果到一个文件
        std::string result;
        if (fp)
        {
            char line[1024];
            while(fgets(line, sizeof(line), fp))
            {
                result += line;
            }
            return result.empty() ? "success" : result;
        }
        else
        {
            return "execute error";
        }
    }
    void HandlerCommand(int sockfd, InetAddr addr)
    {
        while (true)
        {
            char commandffer[1024];
            ssize_t n = ::recv(sockfd, commandffer, sizeof(commandffer) - 1, 0); //TODO
            if (n > 0)
            {
                commandffer[n] = 0;
                LOG(INFO, "get message from client %s, command : %s\n", addr.AddrStr().c_str(), commandffer);
                std::string result = Execute(commandffer);
                ::send(sockfd, result.c_str(), result.size(), 0);
            }
            else if (n == 0)
            {
                LOG(INFO, "client %s quit \n", addr.AddrStr().c_str());
                break;
            }
            else
            {
                break;
                LOG(ERROR, "read error \n");
            }
        }
    }
private:
    std::set<std::string> _safe_command;
};